package com.bdqn.service.impl;

import ch.qos.logback.core.util.StringUtil;
import com.alibaba.fastjson2.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.bdqn.mapper.UserMapper;
import com.bdqn.pojo.User;
import com.bdqn.service.UserService;
import jakarta.annotation.Resource;
import org.apache.shiro.crypto.hash.Md5Hash;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.CachePut;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;

/**
 * 用户Service实现
 *
 * @author LILIBO
 * @since 2024/09/07
 */
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {

    @Resource
    private UserMapper userMapper;

    /**
     * 用户登录
     *
     * @param usrName
     * @param usrPassword
     * @return
     */
    @Override
    public User login(String usrName, String usrPassword) {
        if (StringUtil.isNullOrEmpty(usrName) || StringUtil.isNullOrEmpty(usrPassword)) {
            return null;
        }
        User user = userMapper.getByUsrName(usrName);
        if (!usrPassword.equals(user.getUsrPassword())) {
            return null;
        }
        return user;
    }

    /**
     * 保存或修改用户（如果有主键ID则修改，没有则保存）
     *
     * @param user 用户
     * @return
     * @CachePut 首先执行方法体，执行完毕后根据参数设置进行缓存覆盖
     * value: 缓存名称
     * key: 缓存的键值
     * condition: 满足条件的调用，结果才会被缓存（不指定时相当于true-缓存）
     * unless: 不合适的返回，结果不缓存（不指定时相当于false-缓存）
     * 总结: 当condition=false一定不缓存；当condition=true且unless=true不缓存；当condition=true且unless=false缓存
     */
    @Override
    @CachePut(value = "user", key = "'usrId:' + #user.usrId", condition = "#user!=null", unless = "#result==null")
    @CacheEvict(value = "user", allEntries = true)
    public User saveUser(User user) {
        // 将原始密码进行加密处理
        user.setUsrPassword(this.encryptPassword(user.getUsrPassword()));
        boolean isok = super.saveOrUpdate(user); // 使用MyBatis-Plus提供的方法
        /* if (isok) {
            return super.getById(user.getUsrId());
        } */
        return user;
    }

    /**
     * 根据ID删除用户
     *
     * @param usrId
     * @CacheEvict 清除指定缓存，当数据发生改变时需要清除缓存中不一致的数据
     * allEntries: 所有条目
     * @Caching(evict = {@CacheEvict("cacheKey1"), @CacheEvict(value = "cacheKey2", allEntries = true)}) // 清除多个缓存
     */
    @Override
    @CacheEvict(cacheNames = "user", allEntries = true) // 清除缓存
    // @Caching(evict = {@CacheEvict("role"), @CacheEvict(value = "user", allEntries = true)}) // 清除多个缓存
    public boolean deleteUser(Long usrId) {
        return super.removeById(usrId);
    }

    /**
     * 通过用户ID获取用户对象
     *
     * @param usrId
     * @return
     */
    @Override
    @Cacheable(value = "user", key = "'usrId:' + #usrId")
    public User getUser(Long usrId) {
        return baseMapper.selectById(usrId);
    }

    /**
     * 根据用户名查找用户及对应的角色
     *
     * @param usrName
     * @return
     * @Cacheable 首先查缓存有就返回，没有就执行方法，方法返回不为空添加缓存
     * value: 缓存名称，可以多个
     * key: 缓存的键值
     * condition: 满足条件的调用，结果才会被缓存（不指定时相当于true-缓存）
     * unless: 不合适的返回，结果不缓存（不指定时相当于false-缓存）
     * 总结: 当condition=false一定不缓存；当condition=true且unless=true不缓存；当condition=true且unless=false缓存
     */
    @Override
    @Cacheable(value = "user", key = "'usrName:' + #usrName", condition = "#usrName!=null", unless = "#result==null")
    public User getByUsrName(String usrName) {
        return userMapper.getByUsrName(usrName);
    }

    /**
     * 根据用户名和角色ID分页查询用户数据
     *
     * @Cacheable 首先查缓存有就返回，没有就执行方法，方法返回不为空添加缓存
     * value: 缓存名称，可以多个
     * key: 缓存的键值
     * keyGenerator = "keyGenerator": 缓存的key自动生成
     * condition: 满足条件的调用，结果才会被缓存（不指定时相当于true-缓存）
     * unless: 不合适的返回，结果不缓存（不指定时相当于false-缓存）
     * 总结: 当condition=false一定不缓存；当condition=true且unless=true不缓存；当condition=true且unless=false缓存
     */
    @Override
    // @Cacheable(value = "userPage", keyGenerator = "keyGenerator") // 每次都是新的page对象，无法实现缓存
    @Cacheable(value = "user", key = "'page:' + #page.current + '-' + #page.size + '-' + #usrName + '-' + #roleId", condition = "#page.current!=null and #page.size!=null", unless = "#result==null")
    public Page<User> findPage(String usrName, Long roleId, Page page) {
        return userMapper.findPage(usrName, roleId, page);
    }

    /**
     * 查询用户名是否存在
     *
     * @param usrName
     */
    @Override
    public User getByUsrNameExceptUsrId(String usrName, Long exceptUsrId) {
        JSONObject json = new JSONObject();
        QueryWrapper<User> qw = new QueryWrapper<>();
        if (exceptUsrId != null) {
            qw.ne("usr_id", exceptUsrId); // usr_id不等于传入的ID
        }
        qw.eq("usr_name", usrName);
        return baseMapper.selectOne(qw);
    }

    /**
     * 加密算法（MD5+盐值加密1024次）注册、修改密码
     *
     * @param plaintextPassword 原密码
     * @return
     * @throws IllegalArgumentException
     */
    @Override
    public String encryptPassword(String plaintextPassword) throws IllegalArgumentException {
        String salt = "czkt";
        Md5Hash md5Hash = new Md5Hash(plaintextPassword, salt, 1024);
        System.out.println(md5Hash);
        return md5Hash.toString();
    }

    /**
     * 根据角色ID获取用户数量
     *
     * @param roleId
     * @return
     */
    @Override
    public long countByRoleId(Long roleId) {
        QueryWrapper<User> qw = new QueryWrapper<>();
        qw.eq("usr_role_id", roleId);
        return super.count(qw);
    }

}




